﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.IService;
using Pay.Service.Cache;
using Pay.TO;
using System.Threading.Tasks;
using Pay.DTO.card;
using System.Security.Cryptography.X509Certificates;
using System.Net;
using System.Net.Security;
using System.Net.Http;
using System.Net.Http.Headers;

namespace Pay.Service {
	public class CardService : MerchantBillService, ICardService, IDisposable {
		private IUnitOfWork _iUnitOfWork;

		public CardService(IUnitOfWork iUnitOfWork, ISettingService iSettingService, IBillService iBillService,
										   IMerchantService iMerchantService, IPaymentService iPaymentService,
										   IPayHtmlService iPayHtmlService, IPayNotifyService iPayNotifyService)
							: base(iUnitOfWork, iSettingService, iBillService, iMerchantService, iPaymentService, iPayHtmlService, iPayNotifyService) {
			_iUnitOfWork = iUnitOfWork;
		}

		private const string api_url = "https://api.51ley.com/apis/";
		private const string stationid = "974483935490736129";
		private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) {
			//直接确认，否则打不开
			return true;
		}
		private async Task<resp_base<T>> GetGateway<T>(string query = "") {
			try {
				ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
				//var head = new Dictionary<string, string>();
				//head.Add("stationid", stationid);
				//var resp = await (api_url + query).WithHeaders(head).GetStringAsync();
				using (var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip }) {
					var httpClient = new HttpClient(handler);
					httpClient.DefaultRequestHeaders.Add("stationid", stationid);
					var httresp = await httpClient.GetAsync(api_url + query);
					var resp = await httresp.Content.ReadAsStringAsync();
					var result = resp.ToObject<resp_base<T>>();
					return result;
				}
			} catch {
				return null;
			}
		}

		/// <summary>
		/// 银行列表
		/// </summary>
		/// <returns>The bank.</returns>
		public async Task<List<bank_resp>> GetBank() {
			var data = await GetGateway<List<bank_resp>>("api/bank");
			if (data == null) return new List<bank_resp>();
			return data.result;
		}

		/// <summary>
		/// 银行卡主题列表
		/// </summary>
		/// <returns>The bank.</returns>
		public async Task<List<banktopic_resp>> GetBankTopic() {
			var data = await GetGateway<List<banktopic_resp>>("api/bank/topic");
			if (data == null) return new List<banktopic_resp>();
			return data.result;
		}

		/// <summary>
		/// 银行卡标签列表
		/// </summary>
		/// <returns>The bank topic.</returns>
		public async Task<List<banktag_resp>> GetBankTag() {
			var data = await GetGateway<List<banktag_resp>>("api/bank/tag");
			if (data == null) return new List<banktag_resp>();
			return data.result;
		}

		/// <summary>
		/// 银行卡通道列表
		/// </summary>
		/// <returns>The bank topic.</returns>
		public async Task<PagedResult<bank_card_resp>> GetBankCard(card_req model) {
			try {
				//var head = new Dictionary<string, string>();
				//head.Add("stationid", stationid);
				//var resp1 = await (api_url + "api/bank/card").WithHeaders(head).PostJsonAsync(model).ReceiveJson<resp_base_ex<List<bank_card_resp>>>();
				var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };
				var httpClient = new HttpClient(handler);
				httpClient.DefaultRequestHeaders.Add("stationid", stationid);
				var content = new StringContent(model.ToJson());
				content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
				var httresp = await httpClient.PostAsync((api_url + "api/bank/card"), content);
				var resp = await httresp.Content.ReadAsStringAsync();
				var result = resp.ToObject<resp_base_ex<List<bank_card_resp>>>();
				if (result.paging != null)
					return new PagedResult<bank_card_resp> {
						page = model.current, size = model.size, total_result = result.paging.total, rows = result.result
					};
				return new PagedResult<bank_card_resp> { page = model.current, size = model.size, total_result = 0 };
			} catch {
				return new PagedResult<bank_card_resp> { page = model.current, size = model.size, total_result = 0 };
			}
		}

		/// <summary>
		/// 银行卡通道列表
		/// </summary>
		/// <returns>The bank card detail.</returns>
		/// <param name="id">卡种通道id.</param>
		public async Task<bank_carddetail_resp> GetBankCardDetail(long id) {
			var data = await GetGateway<bank_carddetail_resp>("api/bank/card/" + id.ToString());
			return data.result;
		}

		/// <summary>
		/// 保存申卡记录
		/// </summary>
		/// <returns>The bank card detail.</returns>
		/// <param name="model">Model.</param>
		public async Task<card_save_resp> Post(card_save_model model) {
			try {
				if (string.IsNullOrEmpty(model.bind_no))
					throw new ServerErrorException("商户需要先实名认证");
				if (string.IsNullOrEmpty(model.mobile))
					throw new ServerErrorException("手机号不能为空");
				if (string.IsNullOrEmpty(model.name))
					throw new ServerErrorException("姓名不能为空");
				if (string.IsNullOrEmpty(model.id_card))
					throw new ServerErrorException("身份证不能为空");
				var merchant = _iMerchantService.Get(model.merchant_no);
				var setting = _iSettingService.Get();
				var binder = _iMerchantService.Get(model.bind_no);
				var dt = DateTime.Now.ToUnix();
				var bank_info = await GetBankCardDetail(model.card_channel_id);
				if (bank_info == null)
					throw new ServerErrorException("您所申请的信用卡不存在");

				//回调地址
				var notify = setting.site.api_url + "/card/notify/";

				var cardApply = new CardApply {
					BankName = bank_info.bankCard.name, BindId = binder.id, IdCard = model.id_card, MerchantId = merchant.id,
					Mobile = model.mobile, Name = model.name, Notify = notify, OrderNo = model.order_no,
					OrderTime = dt, PayInfo = new PayInfo {
						OrderNo = model.order_no, PayChannel = PayChannel.None, PayType = PayType.None,
						PayCode = "", PayName = "网申", SettleType = "T1", PayNo = model.order_no, TransactionNo = model.order_no, CreateTime = DateTime.Now.ToUnix()
					},
					Profit = "[]", Status = 1
				};
				var data = new card_save_req {
					name = model.name, callbackUrl = model.notify, clientNo = model.order_no,
					idCard = model.id_card, mobile = model.mobile, stationBankCardChannelId = model.card_channel_id
				};
				//var head = new Dictionary<string, string>();
				//head.Add("stationid", stationid);
				//var resp1 = await (api_url + "api/station/stationCardAccessRecords/save/976042465012219904")
				//	.WithHeaders(head).PostJsonAsync(data).ReceiveJson<resp_base<card_save_resp>>();
				//var result = resp1.result;
				HttpContent httpContent = new StringContent(data.ToJson());
				var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };
				var httpClient = new HttpClient(handler);
				httpClient.DefaultRequestHeaders.Add("stationid", stationid);
				httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
				var httresp = await httpClient.PostAsync((api_url + "api/station/stationCardAccessRecords/save/976042465012219904"), httpContent);
				var resp = await httresp.Content.ReadAsStringAsync();
				var result = resp.ToObject<resp_base<card_save_resp>>().result;
				if (result != null)
					cardApply.SearchUrl = result.url;
				else
					cardApply.Status = 3;
				context.CardApplys.Add(cardApply);
				int db_result = _iUnitOfWork.Commit();

				return result;
			} catch {
				return null;
			}
		}

		/// <summary>
		/// 获取银行卡申请记录
		/// </summary>
		/// <returns>The bank card detail.</returns>
		/// <param name="orderNo">订单号.</param>
		public card_apply GetByOrderNo(string orderNo) {
			var data = context.CardApplys.FirstOrDefault(c => c.OrderNo == orderNo).ToDtoObject<card_apply>();
			return data;
		}

		/// <summary>
		/// 银行卡申请记录更新
		/// </summary>
		/// <returns>The bank card detail.</returns>
		/// <param name="update">订单号.</param>
		public int CardSuccess(card_update update) {
			var data = context.CardApplys.FirstOrDefault(c => c.OrderNo == update.clientNo);
			data.Status = update.status;
			int result = _iUnitOfWork.Commit();
			return result;
		}
	}
}
